/*
 ============================================================================
 Name        : RIOCode.c
 Author      : Joshua
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include "rio.h"
#include <semaphore.h>

void echo(int connfd) {
	size_t n;
	char buf[MAXLINE];
	rio_t rio;

	Rio_readinitb(&rio, connfd);
	while ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
		printf("server received %d bytes\n", n);
		Rio_writen(STDOUT_FILENO, buf, n);
		printf("\n");
		Rio_writen(connfd, buf, n);
	}
}

void command(void) {
	char buf[MAXLINE];
	if (!fgets(buf, MAXLINE, stdin))
		exit(0); /* EOF */
	printf("%s", buf); /* Process the input command */
}

/*int main(void) {

 //RIO TEST and Learn Dup

 int n;
 rio_t rio;
 char buf[8000];
 int fd = open("/home/joshua/workspace/RIOCode/Debug/makefile", O_RDONLY);
 int fdWrite = open("/home/joshua/workspace/RIOCode/Debug/duptest",
 O_WRONLY);
 int sfd = dup(STDOUT_FILENO);
 dup2(STDOUT_FILENO, sfd);
 dup2(fdWrite, STDOUT_FILENO);
 Rio_readinitb(&rio, fd);
 while ((n = rio_readnb(&rio, buf, 8000)) != 0)
 Rio_writen(STDOUT_FILENO, buf, n);

 if (-1 != dup2(sfd, STDOUT_FILENO)) {
 printf("recover fd ok \n");

 write(STDOUT_FILENO, "stdout\n", 7);
 }


 //echo server
 int clientLen;
 struct sockaddr_in clientAddr;
 int clientfd = open_listenfd(8088);
 //write(clientfd,"Hello,Client.",13);
 while (1) {
 clientLen = sizeof(clientAddr);
 int connfd = accept(clientfd, (SA *) &clientAddr,
 (socklen_t *) &clientLen);
 //		hp = gethostbyaddr((const char*) clientAddr.sin_addr.s_addr,
 //				sizeof(clientAddr.sin_addr.s_addr), AF_INET);
 //		haddrp = inet_ntoa(clientAddr.sin_addr);

 printf("Server connected to %s (%s)\n", "localhost", "localhost");
 echo(connfd);
 close(connfd);
 }


 int listenfd, connfd, port;
 socklen_t clientlen = sizeof(struct sockaddr_in);
 struct sockaddr_in clientaddr;
 fd_set read_set, ready_set;

 port = 8088;
 listenfd = Open_listenfd(port);
 FD_ZERO(&read_set);
 Clear read set
 FD_SET(STDIN_FILENO, &read_set);
 Add stdin to read set
 FD_SET(listenfd, &read_set);
 Add listenfd to read set
 //struct timeval timeout = { 3, 0 };
 //select(listenfd + 1, NULL, NULL, NULL, &timeout);
 while (1) {
 ready_set = read_set;
 select(listenfd + 1, &ready_set, NULL, NULL, NULL);
 if (FD_ISSET(STDIN_FILENO, &ready_set))
 command();  Read command line from stdin
 if (FD_ISSET(listenfd, &ready_set)) {
 connfd = accept(listenfd, (SA *) &clientaddr, &clientlen);
 echo(connfd);  Echo client input until EOF
 close(connfd);
 }
 }

 return EXIT_SUCCESS;
 }*/

/*void *thread(void *vargp) {
 int connfd = *((int *) vargp);
 pthread_detach(pthread_self());
 free(vargp);
 echo(connfd);
 close(connfd);
 return NULL;
 }*/

/*int main() {
 int listenfd, *connfdp, port;
 socklen_t clientlen = sizeof(struct sockaddr_in);
 struct sockaddr_in clientaddr;
 pthread_t tid;
 port = 8088;
 listenfd = Open_listenfd(port);
 while (1) {
 connfdp = malloc(sizeof(int));
 *connfdp = accept(listenfd, (SA *) &clientaddr, &clientlen);
 pthread_create(&tid, NULL, thread, connfdp);
 }
 }*/
/* Thread routine */
void *thread(void *vargp);
sem_t mutex;

/* Thread routine prototype */
/* Global shared variable */
volatile int cnt = 0; /* Counter */
int main(int argc, char **argv) {
	int niters;
	pthread_t tid1, tid2;

	niters = 50000000;
	sem_init(&mutex, 0, 1);
	/* Create threads and wait for them to finish */
	pthread_create(&tid1, NULL, thread, &niters);
	pthread_create(&tid2, NULL, thread, &niters);
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	/* Check result */
	if (cnt != (2 * niters))
		printf("BOOM! cnt=%d\n", cnt);
	else
		printf("OK cnt=%d\n", cnt);
	exit(0);
}

void P(sem_t *sem) {
	if (sem_wait(sem) < 0)
		unix_error("P error");
}

void V(sem_t *sem) {
	if (sem_post(sem) < 0)
		unix_error("V error");
}
/* Thread routine */
void *thread(void *vargp) {
	int i, niters = *((int *) vargp);
	for (i = 0; i < niters; i++) {
		P(&mutex);
		cnt++;
		V(&mutex);
	}
	return NULL;
}

